//
// Created by liu on 2020/8/29.
//

#ifndef SOCKETCLIENT_H
#define SOCKETCLIENT_H
#include <sys/socket.h>
#include <netinet/in.h>
#include <string>
#include "SocketClientFDManage.h"
#include <pthread.h>

//Define client property type.
typedef struct{
    int clientName;                      //Client name
    int *clientFD;                       //Client FD assigned from socket
    const char* serverIP;                //Server IP
    int serverPort;                      //Server port
    ClientBlockType clientBlockType;     //Block socket
    BroadcastEnumType broadcast;         //Broadcast from server
    ServerClientPPType clientPPType;     //Protocol process type
    PPFunctionPointer pPFunctionPointer; //Function pointer to process feedback(for protocol process type)
}ClientPropertyType;

//Client process class.
class SocketClient {

public:
    std::string printErr{"SocketClient Error: "};
    std::string printPre{"SocketClient: "};

    //Constructor
    SocketClient();

    //
    //Client process.
    //
    //Creator new client.
    bool clientCreate(ClientPropertyType *clientProperty);

    //Close client.
    void clientClose(int clientFD);


    //
    //Select process.
    //
private:
    //Select add FD to fd_set.
    void selectAddFDs();

    //Select clear FD from fd_set.
    void selectClearFD(int FD){FD_CLR(FD, &fdArray);}

    //Select deadline config.
    bool selectDeadlineConfig(int second = 0, int usecond = 70000);

    //Select deadline config.
    int selectMonitor(){return select(socketFdClientManage.findMaxFD() + 1, &fdArray, NULL, NULL, &selectDeadline);}


    //
    //Thread task process.
    //
    [[noreturn]] static void *socketClientTask(void *data);


    //
    //Utile functions.
    //
private:
    //Convert from ClientBlockType to string.
    static std::string convertFromClientBlockTypeToString(ClientBlockType clientBlockType);


    //
    //Private variables.
    //
private:
    //Socket file descriptor management.
    SocketClientFDManage socketFdClientManage;
    //Select fd_set.
    fd_set fdArray;
    //Select deadline.
    struct timeval selectDeadline;
    //Thread
    pthread_t taskID;

};


#endif // SOCKETCLIENT_H
